Skip to content

Module Architecture

flowchart TD
    BASE["sadeem_saas_base\nSAAS Base"]
    NPM["sadeem_nginx_proxy_manager\nNginx Proxy Manager"]
    CF["sadeem_cloudflare\nCloudflare"]

    S["sadeem.subscription\ndomain · DNS · Nginx · DB\nbilling · Git · notifications"]
    ST["sadeem.subscription.stage\ndev / test / prod instances"]
    PKG["sadeem.subscription.package\nOdoo module collections"]
    MOD["sadeem.subscription.module\nOdoo module reference"]
    TPL["sadeem.subscription.db.template\npre-built DB snapshots"]
    BKL["sadeem.subscription.backup.line\nbackup file records"]
    COL["sadeem.subscription.collaborator\nteam access + portal invite"]
    UPD["sadeem.subscription.update.request\nresource upgrade requests"]
    LIM["sadeem.subscription.model.limit\nper-model record limits"]

    BASE --> S
    NPM --> S
    CF --> S

    S --> ST
    S --> PKG
    PKG --> MOD
    PKG --> TPL
    S --> BKL
    S --> COL
    S --> UPD
    S --> LIM

    S --> A1([action_confirm\nvalidate + start provisioning])
    S --> A2([action_run_subscription\nbuild DNS · Nginx · DB])
    S --> A3([action_stop\npause + redirect traffic])
    S --> A4([action_start\nresume stopped subscription])
    S --> A5([action_cancel\ndelete all resources])
    S --> A6([action_get_subscription_info\nGET slave database info])
    S --> A7([action_execute_sql\nrun SQL on slave DB])
    S --> A8([subscription_diagnosis_fix\nfix DNS · Nginx · DB issues])
    S --> A9([action_sync_model_limits\npush limits to slave])
    S --> A10([action_enable_mobile_notifications\nntfy / FCM token setup])
    S --> A11([action_create_portal_user\ncreate portal user on slave])
    S --> A12([action_create_backup_record\nregister with backup server])
    S --> A13([action_get_backup_line\nsync backup list])
    S --> A14([action_create_code_server\ndeploy VS Code container])
    S --> A15([action_install_subscription_modules\ninstall modules on slave DB])

Module Description

Core SaaS subscription lifecycle management. Handles subscription provisioning (DNS, Nginx, database), billing via sale orders and invoices, multi-stage environments, collaborator access with portal invites, backup management, resource upgrade requests, model limits, Git integration, push notifications, SQL console, and customer self-service portal.

Dependencies

  • base, web, mail, sale, account, portal
  • sadeem_saas_base
  • sadeem_nginx_proxy_manager
  • sadeem_cloudflare

Menus

SAAS Management
├─ Dashboard
⎢   └─ Subscription Dashboard
├─ Subscriptions
⎢   ├─ Subscriptions
⎢   ├─ Stages
⎢   └─ Update Requests
├─ Data
⎢   ├─ Packages
⎢   ⎢   ├─ Subscription Packages
⎢   ⎢   └─ Subscription Modules
⎢   ├─ Database Templates
⎢   └─ Reserved Domains
└─ Configuration
    └─ Settings

Subscription Lifecycle

The subscription follows a defined state flow from creation to deployment

Draft → Confirm → Build → Run
                    ↓
               Build Failed

Run → Stop → Start (Run)
       ↓
    Terminate / Cancel
State Description
Draft Initial creation, all fields editable
Confirmed Validated, ready for deployment
Building Infrastructure provisioning in progress (DNS, Nginx, Database)
Build Failed Deployment encountered an error
Running Live and accepting traffic
Stopped Paused, can be resumed. Traffic redirected
Terminated Permanently disabled
Cancelled All resources deleted and cleaned up

Key Fields

Subscription (sadeem.subscription)

Field Type Description
partner_id Many2one Customer/client (required)
state Selection Lifecycle state: draft, confirm, build, build_fail, run, stop, terminate, cancel
saas_subscription_type Selection Deployment strategy (docker or dbfilter — added by deployment modules)
domain Char Primary domain for the subscription
start_date / end_date Date Subscription period
user_limit Integer Maximum number of users allowed (required)
subscription_package Many2many Associated Odoo module packages
stage_ids One2many Dev/test/staging environments linked to this subscription
stage_limit Integer Max number of stages allowed
storage_limit Integer Storage quota in MB
storage_used Float Computed total storage used (DB + filestore + addons)
http_port Integer Port the main Odoo instance listens on (set at provisioning)
server_ip Char IP of the server running this subscription
root_server Many2one Root server for SSH operations
backup_server_id Many2one Remote backup server
backup_uuid Char UUID assigned by the backup server
backup_state Selection not_configured, active, inactive, error
keep_latest_backup Integer Number of backups to retain (default: 7)
daily/weekly/monthly_backup_count Integer Backup frequency settings
nginx_server Many2one NPM connector for this subscription
nginx_host Many2one NPM proxy host record
nginx_proxy_create_record Boolean Auto-create Nginx proxy host on provisioning
cloudflare_connector_id Many2one Cloudflare account for DNS management
cloudflare_record Many2one Cloudflare DNS record for this subscription
cloudflare_create_record Boolean Auto-create DNS record on provisioning
cloudflare_proxied_record Boolean Whether DNS record is proxied through Cloudflare
build_step_dns Boolean Whether the DNS provisioning step completed
build_step_nginx Boolean Whether the Nginx provisioning step completed
build_step_instance Boolean Whether the DB/instance provisioning step completed
build_fail_message Text Error message when build fails
git_integration Boolean Whether Git code sync is enabled
saas_repository_id Many2one Linked Git repository
git_branch_name Char Git branch to sync
ntfy_server_id Many2one Push notification server
mobile_notifications_enabled Boolean Whether mobile push notifications are active
ntfy_token Char Per-subscription ntfy token
ntfy_token_status Selection active, expired, not_set
control_model_limit Boolean Whether per-model record limits are enforced
control_model_limit_line One2many Per-model limit rules
collaborator_line One2many Collaborators with access and portal state
uuid Char Unique identifier (auto-generated)
protected_subscription Boolean Prevents accidental deletion
grace_period Integer Days after end date before auto-stopping
redirect_ended_to Char URL to redirect traffic to when subscription ends
saas_slave_enabled Boolean Whether SAAS slave API is enabled
database_template Many2one Pre-built DB template to restore on provisioning

Subscription Stage (sadeem.subscription.stage)

Field Type Description
subscription_id Many2one Parent subscription (required)
domain Char Domain for this stage (required)
state Selection Stage lifecycle: build, run, stop, terminate, cancel
http_port Integer Port this stage's Odoo listens on
empty_database Boolean Create an empty database (no template)
demo_data Boolean Include Odoo demo data
git_branch_name Char Branch override for this stage
cloudflare_record Many2one DNS record for this stage
nginx_host Many2one Nginx proxy host for this stage
database_size / filestore_size / user_addons_size Float Storage usage breakdown in MB
active_user_count Integer Number of active users on this stage
stop_by_cron Boolean Whether this stage was stopped by a scheduled cron

Subscription Package (sadeem.subscription.package)

Field Type Description
module_ids Many2many Odoo modules included in this package
db_template_id Many2one Default database template for this package

Collaborator (sadeem.subscription.collaborator)

Field Type Description
subscription_id Many2one Parent subscription
user_id / partner_id Many2one Collaborator identity
portal_state Selection invited, active, inactive

Model Limit (sadeem.subscription.model.limit)

Field Type Description
subscription_id Many2one Parent subscription
model_name Char Technical Odoo model name to limit
limit Integer Maximum number of records allowed

Key Actions

Action Model Description
action_confirm sadeem.subscription Validates domain, sets main domain/subdomain defaults, moves to confirm; triggers provisioning via action_run_subscription
action_run_subscription sadeem.subscription Provisions DNS (Cloudflare), Nginx proxy, and the Odoo instance (Docker/DBFilter specific)
action_reset_draft sadeem.subscription Resets subscription to draft state
action_stop sadeem.subscription Pauses running subscription; stops Nginx host, redirects traffic
action_start sadeem.subscription Resumes stopped subscription; re-enables Nginx host
action_cancel sadeem.subscription Deletes all provisioned resources (DNS, Nginx, DB); moves to cancel
action_create_stage sadeem.subscription Creates a new dev/test stage environment
action_get_subscription_info sadeem.subscription Fetches live database/user info from the slave Odoo instance
action_execute_sql sadeem.subscription Runs SQL from sql_input on the slave database
subscription_diagnosis_fix sadeem.subscription Detects and repairs broken DNS / Nginx / DB configuration
action_sync_model_limits sadeem.subscription Pushes control_model_limit_line rules to the slave instance
action_enable_mobile_notifications sadeem.subscription Sets up ntfy/FCM token for push notifications
action_create_backup_record sadeem.subscription Registers subscription with the remote backup server
action_get_backup_line sadeem.subscription Syncs backup file list from remote backup server
action_create_code_server sadeem.subscription Deploys VS Code server container for this subscription
action_install_subscription_modules sadeem.subscription Installs Odoo modules from the subscription's packages
action_create_portal_user sadeem.subscription Creates a portal user account on the slave database
action_link_git_webhook sadeem.subscription Registers a GitHub webhook for the linked repository
action_redirect_host_to_ended_link sadeem.subscription Redirects Nginx host to redirect_ended_to URL

Warnings & Important Notes

  • Deletion blocked: Cannot delete a subscription not in draft or cancel state — raises ValidationError.
  • Protected subscriptions: Setting protected_subscription = True raises an error if deletion is attempted.
  • Domain validation: action_confirm raises UserError if no main domain is defined, ValidationError if the domain is already in use or fails format validation.
  • Root server required: action_confirm raises ValidationError if no root server is set when git integration is enabled.
  • Destination addons dir required: Raises ValidationError if destination_addons_dir is empty when git is enabled.
  • ntfy constraints: action_enable_mobile_notifications raises ValidationError if no ntfy server is configured or auto_generate_tokens is not enabled.
  • Nginx host creation failure: action_run_subscription raises ValidationError if Nginx host creation or start fails.
  • Cloudflare record failure: action_run_subscription raises ValidationError if DNS record creation fails.
  • SQL constraint on UUID: _sql_constraints enforces UNIQUE(uuid) on sadeem.subscription.
  • Build step tracking: build_step_dns, build_step_nginx, build_step_instance track which provisioning steps completed; used by subscription_diagnosis_fix to determine what needs repair.
  • Secret key required: Encryption operations raise UserError if the sadeem_saas_secret_key system parameter is missing (set by post-install hook in sadeem_saas_base).
  • Grace period: Subscriptions with an end_date are not stopped immediately; grace_period adds extra days before the scheduled cron stops them.
  • Stage state starts at build: Unlike subscriptions which start at draft, stages default to state build.